﻿using System;
using LIUS.Beta.FileSystem.PathFileSuffix;

namespace KopainConcept
{

    partial class Concept
    {

        /// <summary>This class is an abstraction of every document/note/leaf in a concept/tree.  Se the parent class Concept for how this fits into the layering of the solution.
        /// </summary>
        public class Note
        {

#region  Public structs, enums and classes.

            /// <summary>This enum is a more readable boolean.
            /// </summary>
            public enum ForceOpen
            {
                Yes = 1,
                No
            }

#endregion  Public structs, enums and classes.

#region	Private properties.

            /// <summary>This property is the payload.  If set to null we do not know what the payload is.
            /// </summary>
            private string _data;

            /// <summary>Thiis property is the id of the Note.
            /// </summary>
            private Guid _id;

            /// <summary>This property is the title of the Note - what is shown in the tree in the GUI.
            /// </summary>
            private string _title;

            /// <summary>This property is the file name as it is stored on the harddisk.
            /// </summary>
            private FilenameSuffix _filenameSuffix;

            /// <summary>This property is the zero based cursor position.
            /// </summary>
            private int _cursorPosition;

#endregion	//	Private properties.

#region	Public properties.

            /// <summary>This is a property for the payload.
            /// </summary>
            public string Data { get { return _data; }set { _data = value; }}

            /// <summary>This property returns true if the note has Data.  Right nowi it is just a check if _data is null or not but it is a good rule to use this property instead of calling (null != _data) 
            /// since the use of _data might change in the future.
            /// </summary>
            public bool HasData { get { return null != _data; } }

            /// <summary>This getter retrieves the id of the note.
            /// </summary>
            public Guid ID { get {
                return _id; 
            } }

            public FilenameSuffix FilenameSuffix
            {
                get
                {
                    return _filenameSuffix;
                }
            }

            /// <summary>This getter retrieves the title of the Note.  The title is what is shown in the tree in the GUI.
            /// </summary>
            public string Title
            {
                get
                {
                    System.Diagnostics.Debug.Assert(null != _title, "I strongly doubt a null value should be presented publicly.");
                    return _title;
                }
            }

#endregion	//	Public properties.

#region	Constructors.

            /// <summary>This constructor takes alll necessary parameters.
            /// </summary>
            /// <param name="id"></param>
            /// <param name="title"></param>
            /// <param name="filenameSuffix"></param>
            /// <param name="cursorPosition"></param>
            internal Note(Guid id, string title, FilenameSuffix filenameSuffix, int cursorPosition)
            {
                _id = id;
                _title = title;
                _filenameSuffix = filenameSuffix;
                _cursorPosition = cursorPosition;
            }

            /// <summary>This constructor creates all data for a new Note.  Nothing is saved on the harddisk in this constructor.
            /// </summary>
            /// <param name="path"></param>
            /// <returns></returns>
            internal static Note CreateEmpty(Path path)
            {
                return new Note(Guid.NewGuid(), "new note", CreateNewFileName(path), 0);
            }

#endregion	//	Constructors.

#region	Public methods.

            /// <summary>This method makes sure there are data in the Note.  Depending on the parameter data is read from the repository (hard disk) even though there are data from before.
            /// </summary>
            /// <param name="path"></param>
            /// <param name="forceOpen"></param>
            public void Open(Path path, ForceOpen forceOpen)
            {
                if( ForceOpen.Yes == forceOpen || false == HasData )
                {
                    PathFilenameSuffix pathFilenameSuffix = new PathFilenameSuffix(path, _filenameSuffix);    // System.IO.Path.Combine(path, this.FilenameAndSuffix);
                    using (System.IO.StreamReader sr = System.IO.File.OpenText(pathFilenameSuffix.ToString()))
                    {
                        this._data = sr.ReadToEnd();
                        sr.Close();
                    }                    
                }
            }

            /// <summary>This method saves the Data property.
            /// It returns true if something was saved - false if nothing is touched.
            /// </summary>
            /// <param name="path"></param>
            /// <returns></returns>
            internal bool SaveData(Path path)
            {
                if (HasData)
                {
                    PathFilenameSuffix pathFilenameSuffix = new PathFilenameSuffix(path, _filenameSuffix);
                        // System.IO.Path.Combine(path, this.FilenameAndSuffix);
                    using (System.IO.StreamWriter sw = System.IO.File.CreateText(pathFilenameSuffix.ToString()))
                    {
                        sw.Write(this._data);
                        sw.Close();
                    }
                    return true;
                }
                return false;
            }

            #endregion	//	Public methods.

#region	Private methods.

            /// <summary>This helper method returns a new filename that doesn't exist in the folder (path).
            /// </summary>
            /// <param name="path"></param>
            /// <returns></returns>
            private static FilenameSuffix CreateNewFileName(Path path)
            {
                System.Diagnostics.Debug.Assert(path.ToString().EndsWith(System.IO.Path.DirectorySeparatorChar.ToString()));

                //TODO:Write code to find a unique filename.
                return new FilenameSuffix("NewNote.kopain.txt", AllowPeriod.Yes, RequireSuffix.Yes);
            }

#endregion	//	Private methods.

        }

    }

}
